// Author: 		ngohaibac@hocdelam.org
// Date:		16th Nov, 2009
// Hardware:	TMS320F28335
// Module:		PWM Module

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File

#include "DSP2833x_PWMLib.h"

volatile struct EPWM_REGS *ePWM[] =
 			 { &EPwm1Regs,	&EPwm2Regs,	&EPwm3Regs,	&EPwm4Regs,	&EPwm5Regs,	&EPwm6Regs};

void (* InitPWMGpioFcn[])(void) = { &InitEPwm1Gpio,&InitEPwm2Gpio,&InitEPwm3Gpio,&InitEPwm4Gpio,&InitEPwm5Gpio,&InitEPwm6Gpio};

/*
typedef struct
{
   volatile struct EPWM_REGS *EPwmRegHandle;
   Uint16 EPwm_CMPA_Direction;
   Uint16 EPwm_CMPB_Direction;
   Uint16 EPwmTimerIntCount;
   Uint16 EPwmMaxCMPA;
   Uint16 EPwmMinCMPA;
   Uint16 EPwmMaxCMPB;
   Uint16 EPwmMinCMPB;
}EPWM_INFO;
*/

//====================================================
// Initialize for only PWM Module 1
//====================================================
void PWM_Init(enum EPWM_Group PWM_Item, Uint16 period){	
	volatile struct EPWM_REGS *EPwmRegs = ePWM[PWM_Item];	
	// Step 1: Initialize PWM GPIO
	//InitEPwmGpio();	
	(*InitPWMGpioFcn[PWM_Item])();
	
	EALLOW;
   	SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
   	EDIS;
	
	//-------------------------------------------------
	// Step 2: Time-base Clock
	//-------------------------------------------------	
	// Clock: TBCLK = SYSCLKOUT/ (HSPCLKDIV* CLKDIV) => Time-base Clock = 150Mhz
	EPwmRegs->TBCTL.bit.CLKDIV = TB_DIV1;			// CLKDIV = 2^val
	EPwmRegs->TBCTL.bit.HSPCLKDIV = TB_DIV1;		// HSPCLKDIV = 2^val
	
	EPwmRegs->TBCTL.bit.FREE_SOFT = 0;	
	EPwmRegs->TBCTL.bit.PHSDIR = TB_DOWN;
	EPwmRegs->TBCTL.bit.PHSEN = TB_DISABLE;				// Disable load time-base counter from time-base phase
	EPwmRegs->TBCTL.bit.PRDLD = TB_SHADOW;
	EPwmRegs->TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;		// Phase loading is disabled
	EPwmRegs->TBCTL.bit.CTRMODE = TB_COUNT_UP;			// Count up mode
	// Period
	EPwmRegs->TBPRD = period-1;	
	EPwmRegs->TBPHS.half.TBPHS = 0x0000;       			// Set phase register to zero
	EPwmRegs->TBCTR = 0x0000;							// Clear TB Counter	
	
	//-------------------------------------------------
	// Step 3: Compare module
	//-------------------------------------------------
	EPwmRegs->CMPCTL.bit.SHDWAMODE = CC_SHADOW;
	EPwmRegs->CMPCTL.bit.SHDWBMODE = CC_SHADOW;
	EPwmRegs->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;		// Load compare when TBCTR = Zero
	EPwmRegs->CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;		// Load compare when TBCTR = Zero
	
	// Update compare values
	EPwmRegs->CMPA.half.CMPA = 600;
	EPwmRegs->CMPB = 400;	
	
	//--------------------------------------------------
	// Step 4: Set AQ Module: Set form of PWM Signal: should be manual
	//--------------------------------------------------
	
	EPwmRegs->AQCTLA.bit.ZRO = AQ_SET;
	EPwmRegs->AQCTLA.bit.CAU = AQ_CLEAR;
	
	EPwmRegs->AQCTLB.bit.ZRO = AQ_SET;
	EPwmRegs->AQCTLB.bit.CBU = AQ_CLEAR;				
}

//======================================================
// Start Sync for all PWM
//======================================================
void PWM_StartSync(void){
	
	EALLOW;
   	SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
   	EDIS;   	
}

//======================================================
// Set Duty
//======================================================
void PWM_SetDuty(enum EPWM_Group PWM_Item,Uint16 DutyA, Uint16 DutyB){
	volatile struct EPWM_REGS *EPwmRegs = ePWM[PWM_Item];
	
	EPwmRegs->CMPA.half.CMPA = DutyA; 
	EPwmRegs->CMPB = DutyB;
}
